home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’93
/
Wavy
/
Experiments
/
dynamicMap
/
dynamicmap.c
next >
Wrap
C/C++ Source or Header
|
1993-06-18
|
10KB
|
410 lines
/*
Test mappings
*/
#include <QDOffscreen.h>
#include <FixMath.h>
#include "instructions.h"
long Microseconds() = 0xA093;
#define pictID 128
#define kFrameCount 16 // 16 and 32 are kinda nice
void
MakeSineTable(short *theTable)
{
#define cycleSize (kFrameCount / 2)
#define twoPiOverCycleSize (205887/cycleSize)
#define amplitude 4
short i;
for (i = 0; i < 32; i++)
*theTable++ = (amplitude * Frac2Fix(FracSin(i * twoPiOverCycleSize))+32768) >> 16;
}
void MapCoordinates(short width, short height, short x, short y,
short *resultX, short *resultY,
short frameNumber,
short *theTable)
{
#define HorizontalSineWave 0
#define VerticalSineWave 1
#define Mirror 0
#define Identity 0
#if Identity
*resultX = x;
*resultY = y;
#endif
#if Mirror
*resultX = width - x;
*resultY = y;
#endif
#if HorizontalSineWave
*resultX = x + (18 * Frac2Fix(FracSin(y * twoPiOverCycleSize))+32768) >> 16;
*resultY = y;
#endif
#if VerticalSineWave
*resultX = x;
*resultY = y + theTable[(x + frameNumber) % 32];
#endif
while (*resultX < 0)
*resultX += width;
while (*resultY < 0)
*resultY += height;
*resultX %= width;
*resultY %= height;
}
/*
Generate the addresses for one 32-pixel column.
*/
void
GenerateMappingColumn( long *buffer1, short width, short height, short rowBytes,
short frameNumber, short *theTable)
{
long *offsetHere;
short x, y;
offsetHere = buffer1;
for (y = 0; y < height; ++y) {
for (x = 0; x < 32; ++x)
{
short destinationX, destinationY;
MapCoordinates(width, height, x, y, &destinationX, &destinationY,
frameNumber, theTable);
*offsetHere++ = (long)destinationY * rowBytes + destinationX;
}
}
}
void
BlitOneColumn(char *sourceBase, char *destinationBase, short height,
short rowBytes, long *columnMapping)
{
short x, y;
char *sourceRow, *sourceByte;
long *offsetHere;
for (y = 0; y < height; ++y)
{
short byte;
sourceByte = sourceBase;
for (byte = 0; byte < 32; ++byte)
*(destinationBase + *columnMapping++) = *sourceByte++;
sourceBase += rowBytes;
}
}
//
// Blit the entire bitmap from source to dest using a technique similar to what
// we'd like to compile.
//
// Use 5 destination registers so we can use 16-bit constant offsets in instructions
// of the form:
//
// move.b (sourceRow)+, tableValue(destReg[0..4])
//
//
#define EMIT_POSTINC 0
void
WriteSomeCode(short height, short rowBytes, long *mappingTable, short *theCode)
{
short i, x, y;
long destRegisters[5];
long targetByte;
*(*(short **) &theCode)++ = 0xa9ff;
for (i = 0; i < 5; i++)
destRegisters[i] = 32768 + i * 65536L;
for (y = 0; y < height; ++y)
{
for (x = 0; x < 32; ++x) {
long registerOffset;
targetByte = *mappingTable++;
#if EMIT_POSTINC
for (i = 0; i < 5; i++) {
registerOffset = targetByte - destRegisters[i];
if (registerOffset >= -32768 && registerOffset < 32768) {
switch(i) {
case 0:
*(*(short **) &theCode)++ = move_b_a5plus_a0;
*(*(short **) &theCode)++ = registerOffset;
break;
case 1:
*(*(short **) &theCode)++ = move_b_a5plus_a1;
*(*(short **) &theCode)++ = registerOffset;
break;
case 2:
*(*(short **) &theCode)++ = move_b_a5plus_a2;
*(*(short **) &theCode)++ = registerOffset;
break;
case 3:
*(*(short **) &theCode)++ = move_b_a5plus_a3;
*(*(short **) &theCode)++ = registerOffset;
break;
case 4:
*(*(short **) &theCode)++ = move_b_a5plus_a4;
*(*(short **) &theCode)++ = registerOffset;
break;
default:
Debugger();
break;
}
break;
}
}
#else
for (i = 0; i < 0; i++) {
registerOffset = targetByte - destRegisters[i];
if (registerOffset >= -32768 && registerOffset < 32768) {
switch(i) {
case 0:
*(*(short **) &theCode)++ = move_b_off_a5_to_a0;
*(*(short **) &theCode)++ = x;
*(*(short **) &theCode)++ = registerOffset;
break;
case 1:
*(*(short **) &theCode)++ = move_b_off_a5_to_a1;
*(*(short **) &theCode)++ = x;
*(*(short **) &theCode)++ = registerOffset;
break;
case 2:
*(*(short **) &theCode)++ = move_b_off_a5_to_a2;
*(*(short **) &theCode)++ = x;
*(*(short **) &theCode)++ = registerOffset;
break;
case 3:
*(*(short **) &theCode)++ = move_b_off_a5_to_a3;
*(*(short **) &theCode)++ = x;
*(*(short **) &theCode)++ = registerOffset;
break;
case 4:
*(*(short **) &theCode)++ = move_b_off_a5_to_a4;
*(*(short **) &theCode)++ = x;
*(*(short **) &theCode)++ = registerOffset;
break;
default:
Debugger();
break;
}
break;
}
}
// So, we have no register coverage for the destination
// We'll have to emit some slower code.
registerOffset = targetByte - 32768;
*(*(short **) &theCode)++ = immediate_long_load_d0;
*(*(long **) &theCode)++ = registerOffset;
*(*(short **) &theCode)++ = move_byte_da5_a0_d0_L;
*(*(short **) &theCode)++ = x;
*(*(short **) &theCode)++ = no_constant_for_load;
#endif
}
// add rowbytes to the row register
*(*(short **) &theCode)++ = adda_w_const_a5;
#if EMIT_POSTINC
*(*(short **) &theCode)++ = rowBytes - 32;
#else
*(*(short **) &theCode)++ = rowBytes;
#endif
}
*(*(short **) &theCode)++ = rts;
}
//
// Blit the entire bitmap from source to dest, using the same column
// mappings for each column across
//
void
BlitColumns(char *sourceBase, char *destinationBase, short height, short width,
short rowBytes, long *columnMapping)
{
short x, y;
char *sourceRow, *sourceByte;
long *offsetHere;
for (x = 0; x < width; x += 32)
{
char *destinationRow;
offsetHere = columnMapping;
sourceRow = sourceBase + x;
destinationRow = destinationBase + x;
BlitOneColumn(sourceRow, destinationRow, height, rowBytes, offsetHere);
}
}
main()
{
WindowPtr sourceWindow, destinationWindow;
Rect sourceRect, destRect;
Rect frame;
PicHandle picture;
GWorldPtr sourceGWorld, destinationGWorld;
PixMapHandle sourcePix, destinationPix;
GWorldPtr savedGWorld;
GDHandle savedGDevice;
short height, width, rowBytes;
short i, x, y;
long *buffer1, *offsetHere;
char *sourceBase, *destinationBase;
long *ColumnMaps[kFrameCount];
short *FrameCode[kFrameCount];
short wavyTable[32];
InitGraf(&qd.thePort);
InitWindows();
picture = GetPicture(pictID);
frame = (**picture).picFrame;
width = frame.right - frame.left;
height = frame.bottom - frame.top;
SetRect(&sourceRect, 50, 50, width + 50, height + 50);
destRect = sourceRect;
OffsetRect(&destRect, 0, 220);
sourceWindow = NewCWindow(nil,&sourceRect,
"\pSource", TRUE,
documentProc, (WindowPtr)(-1), FALSE, 0);
destinationWindow = NewCWindow(nil,&destRect,
"\pDestination", TRUE,
documentProc, (WindowPtr)(-1), FALSE, 0);
GetGWorld(&savedGWorld, &savedGDevice);
NewGWorld(&sourceGWorld,8,&frame,nil,nil,0);
NewGWorld(&destinationGWorld,8,&frame,nil,nil,0);
sourcePix = GetGWorldPixMap(sourceGWorld);
LockPixels(sourcePix);
SetGWorld(sourceGWorld, nil);
DrawPicture(picture,&sourceGWorld->portRect);
UnlockPixels(sourcePix);
LockPixels(destinationPix);
SetGWorld(destinationGWorld, nil);
EraseRect(&destinationGWorld->portRect);
UnlockPixels(destinationPix);
SetGWorld(savedGWorld, savedGDevice);
sourcePix = GetGWorldPixMap(sourceGWorld);
destinationPix = GetGWorldPixMap(destinationGWorld);
rowBytes = (**GetGWorldPixMap(sourceGWorld)).rowBytes & 0x7FFF;
SetPort(sourceWindow);
LockPixels(sourcePix);
CopyBits((BitMap *)*sourcePix, &sourceWindow->portBits,
&sourceGWorld->portRect, &sourceWindow->portRect, srcCopy, nil);
UnlockPixels(sourcePix);
SetPort(destinationWindow);
LockPixels(sourcePix);
LockPixels(destinationPix);
MakeSineTable(wavyTable);
for (x = 0; x < kFrameCount; x++)
{
ColumnMaps[x] = (long *)NewPtr(sizeof(long) * 32 * height);
if (ColumnMaps[x] == nil)
Debugger();
FrameCode[x] = (short *) NewPtr(12L * 32 * height // move the rows
+ 6 * 20 * height // the row reloads
+ 500); // el sloppolo
if (FrameCode[x] == nil)
Debugger();
GenerateMappingColumn(ColumnMaps[x], width, height, rowBytes, x, wavyTable);
WriteSomeCode(height, rowBytes, ColumnMaps[x], FrameCode[x]);
// DisposePtr((Ptr)ColumnMaps[x]);
MoveTo(width / 2 - 20, x * 3 + 10); // amuse the user
LineTo(width / 2 + 20, x * 3 + 10);
}
SetPort(destinationWindow);
sourceBase = (**sourcePix).baseAddr;
destinationBase = (**destinationPix).baseAddr;
while (!Button()) {
short *theCode;
char *sourceRow;
char *destinationRow;
long startTime, endTime;
for (i = 0; i < kFrameCount ; i++) {
theCode = FrameCode[i];
// BlitColumns(sourceBase, destinationBase, height, width,
// rowBytes, ColumnMaps[i]);
for (x = 0; x < width; x += 32) {
sourceRow = sourceBase + x;
destinationRow = destinationBase + x;
startTime = Microseconds();
asm {
movem.l a0-a6, -(sp)
movea.l destinationRow, a0
adda.l #0x8000, a0
movea.l a0, a1
adda.l #0x10000, a1
movea.l a1, a2
adda.l #0x10000, a2
movea.l a2, a3
adda.l #0x10000, a3
movea.l a3, a4
adda.l #0x10000, a4
movea.l sourceRow, a5
movea.l theCode, a6
jsr (a6) // whee!
movem.l (sp)+, a0-a6
}
endTime = Microseconds();
Debugger();
}
CopyBits((BitMap *)*destinationPix, &destinationWindow->portBits,
&destinationGWorld->portRect, &destinationWindow->portRect, srcCopy, nil);
if (Button())
break;
}
}
UnlockPixels(sourcePix);
UnlockPixels(destinationPix);
}